Skip to content

v0.6.60: copilot security improvements, slack canvas ops, retention jobs fixes#4308

Merged
icecrasher321 merged 5 commits intomainfrom
staging
Apr 27, 2026
Merged

v0.6.60: copilot security improvements, slack canvas ops, retention jobs fixes#4308
icecrasher321 merged 5 commits intomainfrom
staging

Conversation

@icecrasher321
Copy link
Copy Markdown
Collaborator

waleedlatif1 and others added 5 commits April 27, 2026 11:05
* fix(security): patch copilot tool & multipart upload IDORs

- multipart upload: bind upload session to (userId, workspaceId, key)
  via short-lived HMAC-signed token; require workspace write access at
  initiate; source key/uploadId/context from verified token (never
  client) at get-part-urls/complete/abort
- copilot knowledge-base tools: gate all 11 read/write/tag/connector
  ops with checkKnowledgeBaseAccess / checkKnowledgeBaseWriteAccess
- copilot user-table tools: add workspace-id check to get, get_schema,
  add/rename/delete/update_column to match existing op pattern
- copilot manage-credential: add full ownership/write-permission auth
  via getCredentialActorContext (previously had no auth)
- copilot restore-resource: verify workspace ownership and write
  permission for workflow, table, knowledgebase, file, and folder
  restores
- copilot folder rename/move: verify both folderId and parentId belong
  to the caller's workspace via new verifyFolderWorkspace helper
- copilot get-job-logs: verify schedule belongs to caller's workspace

* fix(security): address PR review — document IDOR, log count, token split

- knowledge-base delete_document/update_document: verify each document
  belongs to the claimed knowledgeBaseId via checkDocumentWriteAccess
  (was: trusted args.knowledgeBaseId without binding it to the document)
- multipart batch complete: log verifiedEntries.length instead of raw
  client-supplied data.uploads.length
- upload-token: reject tokens with !=2 dot-delimited segments

* fix(security): close folder workspace bypass when workspaceId is falsy
* Avoid bun memory leak bug from TransformStream

* fix(executor): skip content persistence when stream consumer exits early

Previously, if the onStream consumer caught an internal error without
re-throwing, the block-executor would treat the shortened accumulator
as the complete response, persist a truncated string to memory via
appendToMemory, and set it as executionOutput.content.

Track whether the source ReadableStream actually closed (done=true) in
the pull handler. If onStream returns before the source drains, skip
content persistence and log a warning — the old tee()-based flow was
immune to this because the executor branch drained independently of
the client branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix lint

* fix(executor): early-return when no streamed content to make onFullContent symmetric

Previously, executionOutput.content was guarded by `if (fullContent)`
but `onFullContent` fired regardless. The agent-handler implementor
defensively bails on empty/whitespace content, but that's a callee
contract, not enforced at the call site — future implementors could
spuriously persist empty assistant turns to memory.

Hoist the `!fullContent` check to a single early return, so both the
output write and the callback share the same precondition.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(slack): canvas related operations

* extract shared code
* fix(retention-job): add chunking strategy for cleanup

* change stats to be perjob not per chunk
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Apr 27, 2026 7:18pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 27, 2026

PR Summary

High Risk
High risk because it modifies security/authorization paths (multipart uploads and multiple copilot tools) and changes retention-job deletion logic that can affect large-scale data cleanup if misconfigured.

Overview
Security hardening: Multipart upload follow-up calls (get-part-urls, complete, abort) are now bound to a signed uploadToken (new upload-token.ts) and initiate requires workspaceId, validates allowed contexts, and enforces workspace write/admin permissions to prevent IDOR.

Copilot/tool access fixes: Adds stricter workspace scoping and write checks across copilot tools (credential manage, restore resource, job logs, knowledge base ops, table ops, workflow folder mutations) to avoid cross-workspace access.

Retention + executor improvements: Cleanup jobs now use new chunked SELECT/DELETE utilities (selectRowsByIdChunks, chunkedBatchDelete) to avoid large IN (...) timeouts and to align external side effects (S3/chat cleanup) with the exact rows deleted. Streaming execution handling is reworked to avoid TransformStream memory issues on Bun by assembling full content after drain and exposing an onFullContent hook for memory persistence.

Slack canvases: Adds new Slack canvas operations (get_canvas, list_canvases, lookup_canvas_sections, delete_canvas), updates OAuth scopes/descriptions, extends block UI params/outputs, and registers new tools in the registry.

Reviewed by Cursor Bugbot for commit 65e17de. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 27, 2026

Greptile Summary

This release patches several IDOR vulnerabilities in the copilot tools and multipart upload API, refactors cleanup jobs to chunk large workspace ID lists (avoiding Postgres statement timeouts), replaces stream.tee() with a manual ReadableStream consumer to fix a Bun memory leak, and adds four new Slack canvas operations (get_canvas, list_canvases, lookup_canvas_sections, delete_canvas). The security fixes are comprehensive and well-structured. One minor wiring gap was found in the new Slack block: the channel filter for list_canvases is defined in the tool but never populated from the block, making it inaccessible despite PR #4307 intending to expose it.

Confidence Score: 4/5

Safe to merge; security fixes are well-implemented and the one functional gap (list_canvases channel filter) is non-critical.

All findings are P2; security patches are thorough with no observed regressions. The only issue is the missing channel wiring for list_canvases, which is a feature gap not a breakage.

apps/sim/blocks/blocks/slack.ts — list_canvases case is missing the channel parameter wiring.

Important Files Changed

Filename Overview
apps/sim/app/api/files/multipart/route.ts Replaces raw uploadId+key from request body with HMAC-signed upload tokens (bound to userId, workspaceId, context) for all follow-up actions, closing IDOR on get-part-urls, complete, and abort.
apps/sim/lib/uploads/core/upload-token.ts New HMAC-signed upload token module (UploadTokenPayload signed with INTERNAL_API_SECRET, 1h expiry, safe comparison on verify); used by multipart route to bind sessions to users.
apps/sim/lib/copilot/tools/server/knowledge/knowledge-base.ts Adds checkKnowledgeBaseAccess / checkKnowledgeBaseWriteAccess / checkDocumentWriteAccess guards before every read/write operation, closing IDOR across all KB and document sub-operations.
apps/sim/lib/copilot/tools/server/table/user-table.ts Adds workspaceId ownership check (table.workspaceId !== workspaceId) on all table mutation operations, closing cross-workspace IDOR.
apps/sim/lib/copilot/tools/handlers/restore-resource.ts Adds hasWriteAccess() workspace ownership checks before restore for all resource types (workflow, table, file, knowledgebase, folder); performRestoreFolder also verifies workspaceId internally.
apps/sim/lib/copilot/tools/server/jobs/get-job-logs.ts Makes workspace context required (removes the optional guard), and adds workspaceId equality condition to the job log query, preventing cross-workspace log exposure.
apps/sim/lib/copilot/tools/handlers/management/manage-credential.ts Adds getCredentialActorContext ownership check for both rename and delete operations; type + write-access guard applied to all cases.
apps/sim/lib/copilot/tools/handlers/workflow/mutations.ts Adds verifyFolderWorkspace() checks in executeMoveWorkflow (target folder must belong to same workspace) and executeMoveFolder/executeRenameFolder, closing cross-workspace folder IDOR.
apps/sim/lib/cleanup/batch-delete.ts Refactored with chunkedBatchDelete and selectRowsByIdChunks; splits large workspaceId IN-lists into 50-ID chunks to avoid Postgres statement timeout; batchDeleteByWorkspaceAndTimestamp now delegates to the new primitive.
apps/sim/executor/execution/block-executor.ts Replaces stream.tee() with a manual ReadableStream consumer to avoid a Bun memory leak; removes forwardStream/consumeExecutorStream split and consolidates into a single read path with an accumulated buffer.
apps/sim/blocks/blocks/slack.ts Adds four new canvas operations (get_canvas, list_canvases, lookup_canvas_sections, delete_canvas); channelId/manualChannel made conditionally required (not required for list_canvases); block params and output schema extended.
apps/sim/tools/slack/list_canvases.ts New tool for listing Slack canvases via files.list?types=canvas; supports channel, count, page, user, tsFrom, tsTo, teamId filters; channel param defined but not wired from the block.
apps/sim/tools/slack/lookup_canvas_sections.ts New tool for canvases.sections.lookup; parseCriteria() handles both string and object inputs; error handling covers canvas_not_found and missing_scope.
apps/sim/tools/slack/get_canvas.ts New tool wrapping Slack files.info to retrieve canvas metadata by ID; errors handled for file_not_found and not_visible.
apps/sim/tools/slack/delete_canvas.ts New tool for canvases.delete; handles canvas_not_found and canvas_deleting_disabled errors correctly.

Sequence Diagram

sequenceDiagram
    participant Client
    participant MultipartAPI as /api/files/multipart
    participant TokenModule as upload-token.ts
    participant Storage as S3/Blob

    Client->>MultipartAPI: POST ?action=initiate {fileName, workspaceId, context}
    MultipartAPI->>MultipartAPI: getUserEntityPermissions(userId, workspace)
    MultipartAPI->>Storage: initiateMultipartUpload()
    Storage-->>MultipartAPI: {uploadId, key}
    MultipartAPI->>TokenModule: signUploadToken({uploadId, key, userId, workspaceId, context})
    TokenModule-->>MultipartAPI: uploadToken (HMAC-signed)
    MultipartAPI-->>Client: {uploadId, key, uploadToken}

    Client->>MultipartAPI: POST ?action=get-part-urls {uploadToken, partNumbers}
    MultipartAPI->>TokenModule: verifyUploadToken(uploadToken)
    TokenModule-->>MultipartAPI: payload (userId, key, uploadId, context)
    MultipartAPI->>MultipartAPI: assert payload.userId === session.userId
    MultipartAPI->>Storage: getPartUrls(key, uploadId, partNumbers)
    Storage-->>MultipartAPI: presignedUrls
    MultipartAPI-->>Client: {presignedUrls}

    Client->>Storage: PUT parts directly via presigned URLs

    Client->>MultipartAPI: POST ?action=complete {uploadToken, parts}
    MultipartAPI->>TokenModule: verifyUploadToken(uploadToken)
    MultipartAPI->>Storage: completeMultipartUpload(key, uploadId, parts)
    Storage-->>MultipartAPI: {location, path, key}
    MultipartAPI-->>Client: {success, location, path, key}
Loading

Reviews (1): Last reviewed commit: "fix(retention-job): add chunking strateg..." | Re-trigger Greptile

Comment thread apps/sim/blocks/blocks/slack.ts
@icecrasher321 icecrasher321 merged commit 489f2d3 into main Apr 27, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants